﻿using Microsoft.Extensions.Logging;
using NetCoreCMS.DTO;
using NetCoreCMS.IServices;
using Quartz;
using Quartz.Impl;
using Quartz.Spi;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using IScheduler = Quartz.IScheduler;

namespace NetCoreCMS.Quartz
{
    public class ScheduleCenter
    {
        private readonly ILogger<ScheduleCenter> _logger;
        private readonly ISchedulerFactory _schedulerFactory;
        private readonly IJobFactory _iocJobfactory;
        private IScheduler _scheduler;
        public ScheduleCenter(IJobFactory iocJobfactory, ILogger<ScheduleCenter> logger, ISchedulerFactory schedulerFactory)
        {
            this._logger = logger;
            //1、声明一个调度工厂
            this._schedulerFactory = schedulerFactory;
            this._iocJobfactory = iocJobfactory;
        }

        /// <summary>
        /// 添加调度任务
        /// </summary>
        /// <param name="JobName">任务名称</param>
        /// <param name="JobGroup">任务分组</param>
        /// <param name="JobNamespaceAndClassName">任务完全限定名</param>
        /// <param name="JobAssemblyName">任务程序集名称</param>
        /// <param name="CronExpress">Cron表达式</param>
        /// <param name="StarTime">开始时间</param>
        /// <param name="EndTime">结束时间</param>
        /// <returns></returns>
        public async Task<ScheduleResult> AddJobAsync(String JobName, String JobGroup, String JobNamespaceAndClassName, String JobAssemblyName, string CronExpress)
        {
            ScheduleResult result = new ScheduleResult();
            try
            {
                if (string.IsNullOrEmpty(JobName) || string.IsNullOrEmpty(JobGroup) || string.IsNullOrEmpty(JobNamespaceAndClassName) || string.IsNullOrEmpty(JobAssemblyName) || string.IsNullOrEmpty(CronExpress))
                {
                    result.ResultCode = -3;
                    result.ResultMsg = $"参数不能为空";
                    return result;//出现异常
                }
                var starRunTime = DateTime.Now;
                var EndTime = DateTime.MaxValue.AddDays(-1);
                DateTimeOffset endRunTime = DateBuilder.NextGivenSecondDate(EndTime, 1);
                JobKey jobKey = new JobKey(JobName, JobGroup);
                //2、通过调度工厂获得调度器
                _scheduler = await _schedulerFactory.GetScheduler();
                _scheduler.JobFactory = this._iocJobfactory;//  替换默认工厂
               //3、开启调度器
                //await _scheduler.Start();
                if (!_scheduler.IsStarted)
                {
                    await _scheduler.Start();
                }
                if (await _scheduler.CheckExists(jobKey))
                {
                    await _scheduler.PauseJob(jobKey);
                    await _scheduler.DeleteJob(jobKey);
                }
                //4、创建一个触发器
                ICronTrigger trigger = (ICronTrigger)TriggerBuilder.Create()
                                             .StartAt(starRunTime)
                                             .EndAt(endRunTime)
                                             .WithIdentity(JobName, JobGroup)
                                             .WithCronSchedule(CronExpress)
                                             .Build();
                //5、创建任务                
                Assembly assembly = Assembly.Load(JobAssemblyName);
                var jobType = assembly.GetType(JobNamespaceAndClassName);
                if (jobType == null)
                {
                    result.ResultCode = -1;
                    result.ResultMsg = "系统找不到对应的任务，请重新设置";
                    return result;//出现异常
                }
                IJobDetail job = JobBuilder.Create(jobType)
                .WithIdentity(jobKey).UsingJobData("ServerName", _scheduler.SchedulerName)
                .Build();
                //6、将触发器和任务器绑定到调度器中
                await _scheduler.ScheduleJob(job, trigger);                
                return result;
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, nameof(AddJobAsync));
                result.ResultCode = -4;
                result.ResultMsg = ex.ToString();
                return result;//出现异常
            }
        }


        /// <summary>
        /// 暂停指定任务计划
        /// </summary>
        /// <param name="jobName">任务名</param>
        /// <param name="jobGroup">任务分组</param>
        /// <returns></returns>
        public async Task<ScheduleResult> StopJobAsync(string jobName, string jobGroup)
        {
            ScheduleResult result = new ScheduleResult();
            try
            {
                JobKey jobKey = new JobKey(jobName, jobGroup);
                //2、通过调度工厂获得调度器
                _scheduler = await _schedulerFactory.GetScheduler();
                _scheduler.JobFactory = this._iocJobfactory;//  替换默认工厂
                if (await _scheduler.CheckExists(jobKey))
                {
                    await _scheduler.PauseJob(new JobKey(jobName, jobGroup));
                }
                else
                {
                    result.ResultCode = -1;
                    result.ResultMsg = "任务不存在";
                }

            }
            catch (Exception ex)
            {
                _logger.LogError(ex, nameof(StopJobAsync));

                result.ResultCode = -4;
                result.ResultMsg = ex.ToString();
            }
            return result;//出现异常
        }

        /// <summary>
        /// 恢复指定的任务计划,如果是程序奔溃后 或者是进程杀死后的恢复，此方法无效
        /// </summary>
        /// <param name="jobName">任务名称</param>
        /// <param name="jobGroup">任务组</param>
        /// <returns></returns>
        public async Task<ScheduleResult> ResumeJobAsync(string jobName, string jobGroup)
        {
            ScheduleResult result = new ScheduleResult();
            try
            {
                JobKey jobKey = new JobKey(jobName, jobGroup);
                //2、通过调度工厂获得调度器
                _scheduler = await _schedulerFactory.GetScheduler();
                _scheduler.JobFactory = this._iocJobfactory;//  替换默认工厂
                if (await _scheduler.CheckExists(jobKey))
                {
                    //resumejob 恢复
                    await _scheduler.PauseJob(jobKey);
                    await _scheduler.ResumeJob(jobKey);
                }
                else
                {
                    result.ResultCode = -1;
                    result.ResultMsg = "任务不存在";
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, nameof(ResumeJobAsync));

                result.ResultCode = -4;
                result.ResultMsg = ex.ToString();
            }
            return result;
        }

        /// <summary>
        /// 删除指定的任务
        /// </summary>
        /// <param name="jobName">任务名称</param>
        /// <param name="jobGroup">任务组</param>
        /// <returns></returns>
        public async Task<ScheduleResult> DeleteJobAsync(string jobName, string jobGroup)
        {
            ScheduleResult result = new ScheduleResult();
            try
            {
                JobKey jobKey = new JobKey(jobName, jobGroup);
                //2、通过调度工厂获得调度器
                _scheduler = await _schedulerFactory.GetScheduler();
                _scheduler.JobFactory = this._iocJobfactory;//  替换默认工厂
                if (await _scheduler.CheckExists(jobKey))
                {
                    //先暂停，再移除
                    await _scheduler.PauseJob(jobKey);
                    await _scheduler.DeleteJob(jobKey);
                }
                else
                {
                    result.ResultCode = -1;
                    result.ResultMsg = "任务不存在";
                }

            }
            catch (Exception ex)
            {
                _logger.LogError(ex, nameof(ResumeJobAsync));
                result.ResultCode = -4;
                result.ResultMsg = ex.ToString();
            }
            return result;
        }
    }
}
